package com.itaming.lycheeframework.support.datetime;

import com.itaming.lycheeframework.support.utils.NumberUtil;
import com.itaming.lycheeframework.support.utils.StringUtil;

import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 日期时间解析器
 *
 * @author A.Ming
 */
public class DateTimeParser {

    /**
     * 正则表达式模式
     */
    private static final Pattern pattern = Pattern.compile("^(((\\d{4})-)?(\\d{1,2})-(\\d{1,2}))?(\\s?(\\d{1,2}):(\\d{1,2})(:(\\d{1,2}))?)?$");

    /**
     * 解析{@link LocalDateTime}
     *
     * @param source 日期时间字符串
     * @return {@link LocalDateTime}
     * @throws ParseException
     */
    public static LocalDateTime parseLocalDateTime(String source) throws ParseException {
        Matcher matcher = matcher(source);

        Integer year = NumberUtil.toInteger(matcher.group(3), LocalDateTime.now().getYear());
        Integer month = NumberUtil.toInteger(matcher.group(4), 1);
        Integer day = NumberUtil.toInteger(matcher.group(5), 1);
        Integer hour = NumberUtil.toInteger(matcher.group(7), 0);
        Integer minute = NumberUtil.toInteger(matcher.group(8), 0);
        Integer second = NumberUtil.toInteger(matcher.group(10), 0);

        return LocalDateTime.of(year, month, day, hour, minute, second);
    }

    /**
     * 解析{@link LocalDate}
     *
     * @param source 日期时间字符串
     * @return {@link LocalDate}
     * @throws ParseException
     */
    public static LocalDate parseLocalDate(String source) throws ParseException {
        return parseLocalDateTime(source).toLocalDate();
    }

    /**
     * 解析{@link LocalTime}
     *
     * @param source 日期时间字符串
     * @return {@link LocalTime}
     * @throws ParseException
     */
    public static LocalTime parseLocalTime(String source) throws ParseException {
        return parseLocalDateTime(source).toLocalTime();
    }

    /**
     * 解析{@link Date}
     *
     * @param source 日期时间字符串
     * @return {@link Date}
     * @throws ParseException
     */
    public static Date parseDate(String source) throws ParseException {
        LocalDateTime ldt = parseLocalDateTime(source);

        Calendar calendar = Calendar.getInstance();
        calendar.set(ldt.getYear(), ldt.getMonthValue() - 1, ldt.getDayOfMonth(), ldt.getHour(), ldt.getMinute(), ldt.getSecond());

        return calendar.getTime();
    }

    /**
     * 匹配正则
     *
     * @param source 日期时间字符串
     * @return Matcher
     * @throws ParseException 匹配失败时抛出
     */
    private static Matcher matcher(String source) throws ParseException {
        if (StringUtil.isBlank(source)) {
            throw new ParseException("Can not parse blank date string", 0);
        }

        Matcher matcher = pattern.matcher(source.strip());
        if (!matcher.matches()) {
            throw new ParseException("Unparseable date: \"" + source + "\"", 0);
        }

        return matcher;
    }

}
